package com.she.iiicoursecenter.adapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.she.iiicoursecenter.iiiApplication;
import com.she.iiicoursecenter.adapter.iface.IGenView;
import com.she.iiicoursecenter.event.iface.IEventCallback;

import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ListView;

public class GeneralAdapter extends BaseAdapter{

	final int TYPE_ARRAYLIST     = 0;
	final int TYPE_LINKEDHASHMAP = 1;
	final int TYPE_CURSOR        = 2;
	
	int      mDataType = -1;
	Object   mData;
	IGenView mGenerator;
	Context  mContext;
	
	private Map<String, IEventCallback> mCallbacks = new HashMap<String, IEventCallback>();
	
	boolean mHasFooter = false;
	
	public GeneralAdapter(Context context, IGenView generator) {
		this.mGenerator = generator;
		this.mContext   = context;
	}
	
	public GeneralAdapter(Context context, IGenView generator, int dummys) {
		this.mGenerator = generator;
		this.mContext   = context;
		if(dummys > 0) {
			List<Object> dummyData = new ArrayList<Object>();
			for(int i = 0; i < dummys; i++) {
				dummyData.add(new Object());
			}
			setData(dummyData);
		}
	}
	
	public void setCallback(String key, IEventCallback callback) {
		mCallbacks.put(key, callback);
	}
	
	public IEventCallback getCallback(String key) {
		return mCallbacks.get(key);
	}
	
	public Map<String, IEventCallback> getAllCallbacks() {
		return mCallbacks;
	}
	
	public void setListView(AbsListView listView) {
		this.mGenerator.setListview(listView);
	}
	
	public Object getData() {
		return mData;
	}
	
	public void setData(Object object) {
		setData(object, false);
	}
	
	public void setData(Object object, boolean hasFooter)   {
		mHasFooter = hasFooter;
		// Multiple data list without header
		if(object instanceof ArrayList){      
			mDataType = TYPE_ARRAYLIST;
			iiiApplication.Log("setData", "1. mDataType = " + mDataType);
		} else if(object instanceof LinkedHashMap){
			mDataType = TYPE_LINKEDHASHMAP;
			iiiApplication.Log("setData", "2. mDataType = " + mDataType);
		} else if(object instanceof Cursor){
			mDataType = TYPE_CURSOR;
			iiiApplication.Log("setData", "3. mDataType = " + mDataType);
		}
		mData = object;
	}
	
	public int getCount() {
		int count = 0;
		Log.d("GeneralAdapter", "getCount mDataType = " + mDataType);
		switch(mDataType) {
			case TYPE_ARRAYLIST:
				count = ((ArrayList<?>)mData).size();
				iiiApplication.Log("GeneralAdapter", "getCount TYPE_ARRAYLIST count = " + count);
				break;
			case TYPE_LINKEDHASHMAP:
				count = ((LinkedHashMap<?,?>)mData).size();				
//				Iterator<?> iterator = ((LinkedHashMap<?,?>)mData).entrySet().iterator();
//				while(iterator.hasNext()) {
//					Entry<?,?> entry = (Entry<?,?>)iterator.next();
//					if(entry.getValue() instanceof List) {
//						count = count + 1 + ((List<?>)entry.getValue()).size();
//					}
//				}
				iiiApplication.Log("GeneralAdapter", "getCount TYPE_LINKEDHASHMAP count = " + count);
				break;
			case TYPE_CURSOR:
				count = ((Cursor)mData).getCount(); 
				iiiApplication.Log("GeneralAdapter", "getCount TYPE_CURSOR count = " + count);
				break;
			default:
				break;
		}
		if(mHasFooter) count++;
		return count;
	}

	public Object getItem(int position) {
		iiiApplication.Log("GeneralAdapter", "getItem position = " + position);
		Object object = null;
		switch(mDataType) {
			case TYPE_ARRAYLIST:
				if(position < ((ArrayList<?>)mData).size()) object = ((ArrayList<?>)mData).get(position); 
				break;
			case TYPE_LINKEDHASHMAP:
				// Return value may be key or element
				LinkedHashMap<?,?> map = (LinkedHashMap<?,?>)mData;
				Iterator<?> it = map.entrySet().iterator();
				
				int i = 0;
				while(it.hasNext()){
					if (i==position){
						Entry<?,?> entry = (Entry<?,?>)it.next();
						object = entry;
						break;
					}
					i++;
				}				
//				int index = position;
//				while(it.hasNext()) {
//					Entry<?,?> entry = (Entry<?,?>)it.next();
//					if(entry.getValue() instanceof List) {
//						if(index == 0)                                    object = entry.getKey();
//						else if(index <= ((List<?>)entry.getValue()).size()) object = ((List<?>)entry.getValue()).get(index-1);
//						else                                              index = index - ((List<?>)entry.getValue()).size() - 1;
//					}
//				}
				break;
			case TYPE_CURSOR:
				if(position <= ((Cursor)mData).getCount()) object = ((Cursor)mData).moveToPosition(position);
				break;
			default:
				break;
		}
		return object;
	}

	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return 0;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		iiiApplication.Log("GeneralAdapter", "getView position = " + position);
		return mGenerator.setup(mContext, position, convertView, parent, mData);
	}		
}
